import 'dart:io';

import 'package:demo/config/env_config.dart';
import 'package:dio/dio.dart';
import 'package:dio/io.dart';

import '../utils/log_util.dart';
import 'interceptors/ex_options.dart';
import 'interceptors/global_interceptor.dart';

/// 封装参考ai和以下文章
/// https://book.flutterchina.club/chapter15/network.html#_15-5-2-%E5%B0%81%E8%A3%85%E7%BD%91%E7%BB%9C%E8%AF%B7%E6%B1%82
/// https://juejin.cn/post/7488210211380625435
/// https://juejin.cn/post/7475651131449819136
/// https://juejin.cn/post/7472785299732496418
/// https://juejin.cn/post/7342791666075353107
class HttpUtil {
  static final HttpUtil _instance = HttpUtil._internal();
  late Dio _dio;

  factory HttpUtil() {
    return _instance;
  }

  HttpUtil._internal() {
    var options = BaseOptions(
      baseUrl: envConfig.apiUrl, // 替换为你的API基础URL
      connectTimeout: const Duration(seconds: 10),
      receiveTimeout: const Duration(seconds: 10),
      validateStatus: (code) {
        //指定这些HttpCode都算成功
        if (code == 200 || code == 201) {
          return true;
        } else {
          return false;
        }
      },
    );

    _dio = Dio(options);

    /// 全局拦截器
    _dio.interceptors.add(GlobalInterceptor());

    /// 在调试模式下需要抓包调试，所以我们使用代理，并禁用HTTPS证书校验
    if (envConfig.isDebug) {
      _dio.httpClientAdapter = IOHttpClientAdapter(
        createHttpClient: () {
          return HttpClient()
            // 将请求代理到 本机IP:8888，是抓包电脑的IP！！！不要直接用localhost，会报错:
            // SocketException: Connection refused (OS Error: Connection refused, errno = 111), address = localhost, port = 47972
            //   ..findProxy = (uri) {
            //     return 'PROXY 192.168.102.125:8888';
            //   }
            // 抓包工具一般都会提供一个自签名的证书，会通不过证书校验，这里禁用下
            ..badCertificateCallback = (X509Certificate cert, String host, int port) => true;
        },
      );

      /// 请求日志 要放在最后否则不会打印后续添加的Headers
      _dio.interceptors.add(Log.dioLogger);
    }
  }

  /// 网络请求 Get 请求
  Future<T?> get<T>({
    required String url,
    Map<String, dynamic>? params,
    Map<String, String>? headers,
    bool addHeaders = true, // 是否添加公共请求头
    bool addSign = true, // 是否添加签名
    bool showErrorToast = true, // 是否显示错误提示
    bool asHttpResponseData = true, // 请求结果是否转换成HttpResponseData
    CancelToken? cancelToken, // 用于取消的 token，可以多个请求绑定一个 token
  }) async {
    var response = await _dio.get(
      url,
      queryParameters: params,
      options: Options(headers: headers)
        ..addHeaders = addHeaders
        ..addSign = addSign
        ..showErrorToast = showErrorToast
        ..asHttpResponseData = asHttpResponseData,

      cancelToken: cancelToken,
    );
    return response.data;
  }

  /// 网络请求 Post 请求
  Future<T?> post<T>({
    required String url, // 必填的请求URL
    Map<String, dynamic>? params, // 可选的请求参数
    Map<String, List<String>>? files, //文件，键为字段名，值为文件路径列表
    Map<String, String>? headers, // 可选的请求头
    bool addHeaders = true, // 是否添加公共请求头
    bool addSign = true, // 是否添加签名
    bool showErrorToast = true, // 是否显示错误提示
    bool asHttpResponseData = true, // 请求结果是否转换成HttpResponseData
    CancelToken? cancelToken, // 用于取消的 token，可以多个请求绑定一个 token
  }) async {
    var map = <String, dynamic>{};

    //只要有一个不为空，就可以封装参数
    if (params != null || files != null) {
      //默认的参数
      if (params != null) {
        map.addAll(params);
      }

      //File文件
      files?.forEach((key, pathList) {
        map[key] = pathList.map((it) async {
          await MultipartFile.fromFile(it);
        });
      });
    }

    final formData = FormData.fromMap(map);
    var response = await _dio.post(
      url,
      data: formData,
      options: Options(headers: headers)
        ..addHeaders = addHeaders
        ..addSign = addSign
        ..showErrorToast = showErrorToast
        ..asHttpResponseData = asHttpResponseData,
      cancelToken: cancelToken,
    );
    return response.data;
  }
}
